﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
using MySql.Data.MySqlClient;
using System;
using System.IO;
using System.Threading.Tasks;

/*
CREATE TABLE `tmp_file_list` (
	`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID,自增',
	`orig_file_name` varchar(255) NOT NULL COMMENT '文件名',
	`uploader_name` varchar(255) NOT NULL DEFAULT '' COMMENT '上传者姓名',
	`date_uploaded` datetime(0) NOT NULL COMMENT '创建日期',
	`file_length` int(8) UNSIGNED NOT NULL COMMENT '文件长度,最大10MB=10485760字节',
	`file_content` mediumblob NULL COMMENT '文件数据',
	`was_deleted` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '此处置1表示改行已被软删除',
	PRIMARY KEY (`id`)
)
ENGINE = InnoDB
COMMENT = '临时文件列表。其中单个文件最大长度10MB'
ROW_FORMAT = Compact;
*/
namespace LargeFilesSample.Controllers
{
    /// <summary>
    /// controller for upload large file
    /// </summary>
    [ApiController]
    [Route("[controller]")]
    public class FileUploadController : ControllerBase
    {
        private readonly ILogger<FileUploadController> _logger;

        public FileUploadController(ILogger<FileUploadController> logger)
        {
            _logger = logger;
        }

        /// <summary>
        /// Action for upload large file
        /// </summary>
        /// <remarks>
        /// Request to this action will not trigger any model binding or model validation,
        /// because this is a no-argument action
        /// </remarks>
        /// <returns></returns>
        [HttpPost]
        [Route(nameof(UploadLargeFile))]
        public async Task<IActionResult> UploadLargeFile()
        {
            var request = HttpContext.Request;

            // validation of Content-Type
            // 1. first, it must be a form-data request
            // 2. a boundary should be found in the Content-Type
            if (!request.HasFormContentType ||
                !MediaTypeHeaderValue.TryParse(request.ContentType, out var mediaTypeHeader) ||
                string.IsNullOrEmpty(mediaTypeHeader.Boundary.Value))
            {
                return new UnsupportedMediaTypeResult();
            }

            var reader = new MultipartReader(mediaTypeHeader.Boundary.Value, request.Body);
            var section = await reader.ReadNextSectionAsync();

            // This sample try to get the first file from request and save it
            // Make changes according to your needs in actual use
            while (section != null)
            {
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition,
                    out var contentDisposition);

                if (hasContentDispositionHeader && contentDisposition.DispositionType.Equals("form-data") &&
                    !string.IsNullOrEmpty(contentDisposition.FileName.Value))
                {
                    // Don't trust any file name, file extension, and file data from the request unless you trust them completely
                    // Otherwise, it is very likely to cause problems such as virus uploading, disk filling, etc
                    // In short, it is necessary to restrict and verify the upload
                    // Here, we just use the temporary folder and a random file name

                    // 设置文件名和存储路径
                    string rootStorageDir = Path.GetFullPath(@"D:\upload");
                    var fileName = contentDisposition.FileName.Value + "." + Path.GetRandomFileName();
                    var saveToPath = Path.Combine(rootStorageDir, fileName);
                    _logger.LogInformation("======================");
                    _logger.LogWarning($"saveToPath = {saveToPath}");
                    _logger.LogInformation("======================");

                    using (var targetStream = System.IO.File.Create(saveToPath))
                    {
                        await section.Body.CopyToAsync(targetStream);
                    }
                    var origFileName = contentDisposition.FileName.Value;
                    string uploaderName = "王五";
                    var today = DateTime.Now.ToString("G");
                    string sql = "INSERT INTO `tmp_file_list`(`orig_file_name`, `uploader_name`, `date_uploaded`, `file_length`, `file_content`)" +
                        " VALUES (@origFileName, @uploaderName, @dateUploaded, @fileLength, @fileContentBuffer)";

                    using var connection = new MySqlConnection()
                    {
                        ConnectionString = "Database='data2023';Server='localhost';Port=3306;User Id='root';Password='123456';SslMode='none';charset='utf8';pooling=true"
                    };
                    var command = new MySqlCommand
                    {
                        Connection = connection,
                        CommandText = sql
                    };
                    command.Parameters.Clear();
                    command.Parameters.AddWithValue("origFileName", origFileName);
                    command.Parameters.AddWithValue("uploaderName", uploaderName);
                    command.Parameters.AddWithValue("dateUploaded", today);
                    command.Parameters.AddWithValue("fileLength", 0);
                    command.Parameters.AddWithValue("fileContentBuffer", null);

                    try
                    {
                        connection.Open();
                        try
                        {
                            int count = command.ExecuteNonQuery();
                            _logger.LogInformation($"成功修改了count={count}行");
                        } catch(Exception ex)
                        {
                            _logger.LogError("SQL语句执行失败, 详细错误信息如下: " + ex.Message, ex);

                        }
                        finally { connection.Close(); }
                    }
                    catch (MySqlException exception)
                    {
                        _logger.LogError("无法登录MySQL数据库, 错误信息如下:" + exception.Message, exception);
                    }


                    return Ok();

                    //string connectionString = "Database='data2023';Data Source='localhost';Port=3306;User Id='root';Password='123456';charset='utf8';;pooling=true";
                    //using (var sqlConnection = new MySqlConnection(connectionString))
                    //{
                    //    sqlConnection.Open();
                    //
                    //    var accounts = await sqlConnection.QueryAsync<Account>("SELECT * FROM hm_accounts WHERE accountid = @accountid", new
                    //    {
                    //        accountid = id
                    //    });
                    //
                    //    var account = accounts.SingleOrDefault();
                    //
                    //    return account;
                    //}


                    //MySql.Data.MySqlClient.MySqlHelper sqlHelper = new MySqlHelper("");

                    // /*
                    //MySqlCommand command;
                    //string sql = "insert into `book_list`(" +
                    //    "`title`, `author`, `isbn_code`, `published_by`, `publish_date`)"+
                    //    " VALUES " + "('张三自传', '张三', '978-123456789-0', 'xx出版社', '2012-01-01')";
                    //
                    //try
                    //{
                    //    using var connection = new MySqlConnection()
                    //    {
                    //        ConnectionString = "Database='data2023';Data Source='localhost';Port=3306;User Id='root';Password='123456';charset='utf8';pooling=true" 
                    //    };
                    //    connection.Open();
                    //    command = new MySqlCommand(sql, connection);
                    //    int count = command.ExecuteNonQuery();
                    //    _logger.LogInformation($"成功修改了count={count}行");
                    //    connection.Close();
                    //}
                    //catch (MySqlException exception)
                    //{
                    //    _logger.LogError(exception.Message);
                    //}
                    // */

                }

                section = await reader.ReadNextSectionAsync();
            }

            // If the code runs to this location, it means that no files have been saved
            return BadRequest("No files data in the request.");
        }
    }
}
